package com.spring.data.jpa.demo.config;

import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.hibernate.ejb.HibernatePersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 
 * @author Administrator
 * 
 */

// 标注这是一个配置文件
@Configuration
// 事务管理：service层 使用@Transactional注解
@EnableTransactionManagement
// 确定使用的jpa实现，以及扫描dao包
@EnableJpaRepositories("com.spring.data.jpa.demo.core.dao")
public class DatabaseConfig {
	private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
	private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
	private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
	private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
	private static final String PROPERTY_NAME_DATABASE_DIALECT = "hibernate.dialect";
	private static final String PROPERTY_NAME_DATABASE_SHOW_SQL = "hibernate.show_sql";
	private static final String PROPERTY_NAME_DATABASE_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
	private static final String PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";

	/**
	 * 从属性文件jdbc.properties中读取配置值
	 */
	@Resource
	private Environment env;

	/**
	 * 创建数据源<br >
	 * 加载驱动、数据库用户名、密码。此处也可以使用其它的连接池数据源。
	 * 
	 * @return
	 */
	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		dataSource.setDriverClassName(env
				.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
		dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
		dataSource.setUsername(env
				.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
		dataSource.setPassword(env
				.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

		return dataSource;
	}

	/**
	 * 相当于spring 集成 hibernate中的sessionFactory<br >
	 * 加载数据源，以及要扫描的实体包
	 * 
	 * @return
	 */
	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
		entityManagerFactory.setDataSource(dataSource());
		entityManagerFactory
				.setPersistenceProviderClass(HibernatePersistence.class);
		entityManagerFactory
				.setPackagesToScan(env
						.getRequiredProperty(PROPERTY_NAME_DATABASE_ENTITYMANAGER_PACKAGES_TO_SCAN));
		entityManagerFactory.setJpaProperties(hibernateProperties());

		return entityManagerFactory;
	}

	/**
	 * Jpa 实现的事务管理
	 * 
	 * @return
	 */
	@Bean
	public JpaTransactionManager transactionManager() {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory()
				.getObject());

		return transactionManager;
	}

	/**
	 * hibernate 属性配置
	 * 
	 * @return
	 */
	private Properties hibernateProperties() {
		Properties properties = new Properties();
		properties.setProperty(PROPERTY_NAME_DATABASE_DIALECT,
				env.getRequiredProperty(PROPERTY_NAME_DATABASE_DIALECT));
		properties.setProperty(PROPERTY_NAME_DATABASE_SHOW_SQL,
				env.getRequiredProperty(PROPERTY_NAME_DATABASE_SHOW_SQL));
		properties.setProperty(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO,
				env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));

		return properties;
	}
}
